package controlLayer;

import java.util.ArrayList;
import java.util.List;

import modelLayer.Block;
import modelLayer.Schedule;
import modelLayer.ScheduleCon;
import modelLayer.Class;
import modelLayer.TeachingBlock;

public class ScheduleCtr {
	
	private Schedule schedule;
	private ScheduleCon scheduleCon;
	
	public ScheduleCtr() {
		
		scheduleCon = ScheduleCon.getInstance();
	}
	
	public void createSchedule(String className, int period, int number) {
		
		Class cl = new ClassCtr().findClass(className);
		this.schedule = new Schedule(cl, period, number);
		List<Block> list = new ArrayList<>();
		
		for (int i = 1; i <= number; ++i) {
			Block b = this.schedule.createBlock(i);
			b.setSchedule(this.schedule);
			list.add(b);
		}
		
		this.schedule.setBlocks(list);
		
		scheduleCon.addSchedule(schedule);
		cl.setSchedule(schedule);
	
	}
	
	public void moveTeachingBlock(String clName, String tbID, int blockNo) {
		Schedule sch = scheduleCon.findSchedule(clName);
		Class cl = sch.getCl();
		TeachingBlock tb = cl.findTeachingBlock(tbID);
		Block b = sch.findBlock(blockNo);
		
		
		if (!checkConflict(blockNo, tb)){
			b.setTeachingBlock(tb);
			sch.updateBlockCollection(b);
			//System.out.println("Schedule for " + cl.getClassName() + " has been modified.");
		}
		
		else {
			System.out.println("\n" + "Moving the teachingblock " + tbID + " is conflicting on block number " + blockNo + "." );
			System.out.println("\n" + "Consider the following available places: " + showSuggestions(cl, blockNo, tb));//shows a list of blocks where the tb can be placed without conflict
			//showNextSuggestion(blockNo, tb); //there has to be a selection of showSuggestion() or showNextSuggestion()
		}
	}

	private boolean checkConflict(int blockNo, TeachingBlock tb) {
		// get all blocks, which has the same blockNo and which aren't empty
		// iterate through them and compare subject and classroom
		// if subject is the same, return conflict (show conflict message)
		// if classroom is the same, return conflict (show conflict message)
		// ask the user if suggestions are wanted
		// if yes, show suggestions
		// else start over
		// return true if there was no conflict
		
		boolean conflict = false;
		
		List<Block> blocks = scheduleCon.getBlocksByNumber(blockNo);
		for (Block b : blocks){
			if (b.getTeachingBlock().getSubject().equals(tb.getSubject())){
				conflict = true;
			}
			
			else if (b.getTeachingBlock().getClassRoom().equals(tb.getClassRoom())){
				conflict = true;
			}
		}
		
		return conflict;
	}
	
	/**
	 * Shows a list of block numbers which refer to Blocks that are not conflicting with the TeachingBlock
	 * @param tb
	 * @return
	 */
	private List<Integer> showSuggestions(Class cl, int blockNo, TeachingBlock tb){
		//call the checkAllBlock method which checks all the classes blocks &
		//& returns a list of all the free blocks
		//iterate through the list and eliminate those, where the class schedule already contains a teachingBlock
		//return the number of the available blocks by calling a helper method (getFreePlaces)
		
		List<Block> freeBlocks = checkAllBlocks(cl, blockNo, tb);
		
		List<Block> freeBlocksOfClass = new ArrayList<>();
		for (Block b : freeBlocks){
			if (b.getTeachingBlock() == null && b.getSchedule().getCl().equals(cl)){
				freeBlocksOfClass.add(b);
			}
		}
		return getFreePlaces(freeBlocksOfClass);
		
	}
	
	
	/**
	 * Returns a list of available blocks by checking all the blocks on all schedules.
	 * @param cl
	 * @param blockNo
	 * @param tb
	 * @return
	 */
	private List<Block> checkAllBlocks(Class cl, int blockNo, TeachingBlock tb) {
		// get all blocks
		// eliminate those with the conflicting blockNo
		// iterate through the list and compare subject and classroom
		// if block does not have a teachingBlock, add block to the list of free blocks
		// if subject is not the same, add block to the list of free blocks
		// if classroom is not the same, add block to the list of free blocks
		// return the list of freeBlocks
		
		List<Block> freeBlocks = new ArrayList<>();
		
		List<Block> allBlocks = scheduleCon.getAllBlocks();
		for (Block b : allBlocks){
			if (b.getNumber() != blockNo){
				if (b.getTeachingBlock() == null){
					freeBlocks.add(b);
				}
				else if (!b.getTeachingBlock().getSubject().equals(tb.getSubject())){
					freeBlocks.add(b);
				}
				else if (!b.getTeachingBlock().getClassRoom().equals(tb.getClassRoom())){
					freeBlocks.add(b);
				}
			}
		}
		return freeBlocks;
	}

	/**
	 * Helper method to get a list of free places.
	 * @param freeBlocks
	 * @return
	 */
	private List<Integer> getFreePlaces(List<Block> freeBlocks) {
		List<Integer> freePlaces = new ArrayList<>();
		
		for (Block b : freeBlocks){
			freePlaces.add(b.getNumber());
		}
		
		return freePlaces;
	}
	
	
	private Integer showNextSuggestion(int blockNo, TeachingBlock tb){
		// get all blocks
		// eliminate those with the conflicting blockNo
		// iterate through the list check if teachingBlock is null and compare subject and classroom
		// return the number of the first found free block
		// how to save the block number in case of the same method will be called again 
		// 		and we are not interested in finding the same again?? Should the GUI do it?
		
		Block freeBlock = null;
		List<Block> allBlocks = scheduleCon.getAllBlocks();
		boolean found = false;
		
		for (int i = 0; !found && i < allBlocks.size(); i++){
			if (allBlocks.get(i).getNumber() != blockNo){
				if (allBlocks.get(i).getTeachingBlock() == null ||
					!allBlocks.get(i).getTeachingBlock().getSubject().equals(tb.getSubject()) ||
					!allBlocks.get(i).getTeachingBlock().getClassRoom().equals(tb.getClassRoom())){
					
					freeBlock = allBlocks.get(i);
					found = true;
				}
			}
		}
		return freeBlock.getNumber();
	}
	

}
